/// 
/// MaDAson - Toolkit for Model Driven Software Development
/// 
/// Copyright [2006] Marcus Lankenau
/// 
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///  
///     http://www.apache.org/licenses/LICENSE-2.0
///  
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
/// 

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Core;
using NUnit.Framework;

namespace Madason.MetaModel.Interfaces.Tests
{
	[TestFixture]
	public class TestImportXmi11Classmember : TestImportXmi11Base
	{
		const string xmiClassWithAttributes = 
			@"<XMI.content xmlns:UML=""href://org.omg/UML/1.3"">" +
			@"	<UML:Class xmi.id=""UMLClass.3"" name=""SomeClass"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" isActive=""false"">"+
			@"		<UML:Classifier.feature>"+
            @"			<UML:Attribute xmi.id=""UMLAttribute.4"" name=""FirstAttribute"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" changeability=""changeable"" targetScope=""instance"" type=""X.7"" owner=""UMLClass.3""/>"+
            @"			<UML:Attribute xmi.id=""UMLAttribute.5"" name=""SecondAttribute"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" changeability=""changeable"" targetScope=""instance"" type=""X.9"" owner=""UMLClass.3""/>"+
			@"			<UML:Attribute xmi.id=""UMLAttribute.6"" name=""ThirdAttribute"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" changeability=""changeable"" targetScope=""instance"" owner=""UMLClass.3"">" +
			@"				<UML:StructuralFeature.type>" +
			@"					<UML:Classifier xmi.idref=""X.7""/>" +
			@"				</UML:StructuralFeature.type>" +
			@"          </UML:Attribute>" +
			@"	  </UML:Classifier.feature>" +
			@"	</UML:Class>"+
			@"	<UML:DataType xmi.id=""X.7"" name=""int"" visibility=""public"" isSpecification=""false"" isRoot=""false"" isLeaf=""false"" isAbstract=""false""/>"+
			@"	<UML:DataType xmi.id=""X.9"" name=""string"" visibility=""public"" isSpecification=""false"" isRoot=""false"" isLeaf=""false"" isAbstract=""false""/>"+
			@"  <UML:Stereotype xmi.id=""X.6"" name=""PrimaryKey"" extendedElement=""UMLAttribute.4""/>" +
			@"</XMI.content>";

		[Test]
		public void TestLoadAttribute()
		{
			Model model = LoadModel(xmiClassWithAttributes);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(3, cls.Attributes.Count);
		}

		[Test]
		public void TestCheckAttributeName()
		{
			Model model = LoadModel(xmiClassWithAttributes);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(3, cls.Attributes.Count);
			Attribute attr1 = cls.Attributes[0];
			Attribute attr2 = cls.Attributes[1];
			Attribute attr3 = cls.Attributes[2];
			Assert.AreEqual("FirstAttribute", attr1.Name);
			Assert.AreEqual("SecondAttribute", attr2.Name);
			Assert.AreEqual("ThirdAttribute", attr3.Name);
			Assert.AreEqual("UMLAttribute.4", attr1.Id);
			Assert.AreEqual("UMLAttribute.5", attr2.Id);
			
		}

		[Test]
		public void TestCheckAttributeType()
		{
			Model model = LoadModel(xmiClassWithAttributes);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(3, cls.Attributes.Count);
			Attribute attr1 = cls.Attributes[0];
			Attribute attr2 = cls.Attributes[1];
			Attribute attr3 = cls.Attributes[2];
			Assert.IsNotNull(attr1.Type);
			Assert.IsNotNull(attr2.Type);
			Assert.IsNotNull(attr3.Type);
			Assert.AreEqual("int", attr1.Type.Name);
			Assert.AreEqual("string", attr2.Type.Name);
			Assert.AreEqual("int", attr3.Type.Name);
		}

		[Test]
		public void TestAttributeStereotype()
		{
			Model model = LoadModel(xmiClassWithAttributes);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(3, cls.Attributes.Count);
			Attribute attr1 = cls.Attributes[0];
			Attribute attr2 = cls.Attributes[1];
			Assert.AreEqual(Stereotype.PrimaryKey, attr1.Stereotype);
		}


		string xmiOperations = 
			@"<XMI.content xmlns:UML=""href://org.omg/UML/1.3"">" +
			@"	<UML:Class xmi.id=""UMLClass.3"" name=""SomeClass"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" isActive=""false"">"+
			@"		<UML:Classifier.feature>" +
            @"			<UML:Operation xmi.id=""UMLOperation.4"" name=""MethodA"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" isQuery=""false"" concurrency=""sequential"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" specification="""" owner=""UMLClass.3"">" +
            @"				<UML:BehavioralFeature.parameter>" +
            @"					<UML:Parameter xmi.id=""UMLParameter.5"" name="""" visibility=""public"" isSpecification=""false"" kind=""return"" behavioralFeature=""UMLOperation.4"" type=""X.10""/>" +
            @"					<UML:Parameter xmi.id=""UMLParameter.6"" name=""paramA"" visibility=""public"" isSpecification=""false"" kind=""in"" behavioralFeature=""UMLOperation.4"" type=""X.11""/>" +
            @"				</UML:BehavioralFeature.parameter>" +
            @"			</UML:Operation>" +
            @"			<UML:Operation xmi.id=""UMLOperation.7"" name=""MethodB"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" isQuery=""false"" concurrency=""sequential"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" specification="""" owner=""UMLClass.3"">" +
            @"				<UML:BehavioralFeature.parameter>" +
            @"					<UML:Parameter xmi.id=""UMLParameter.8"" name="""" visibility=""public"" isSpecification=""false"" kind=""return"" behavioralFeature=""UMLOperation.7"" type=""X.12""/>" +
            @"					<UML:Parameter xmi.id=""UMLParameter.9"" name=""paramB"" visibility=""public"" isSpecification=""false"" kind=""in"" behavioralFeature=""UMLOperation.7"" type=""X.13""/>" +
            @"				</UML:BehavioralFeature.parameter>" +
            @"			</UML:Operation>" +
			@"		</UML:Classifier.feature>" +
			@"	</UML:Class>" +
			@"  <UML:DataType xmi.id=""X.10"" name=""int"" visibility=""public"" isSpecification=""false"" isRoot=""false"" isLeaf=""false"" isAbstract=""false""/>" +
			@"	<UML:DataType xmi.id=""X.11"" name=""string"" visibility=""public"" isSpecification=""false"" isRoot=""false"" isLeaf=""false"" isAbstract=""false""/>" +
			@"	<UML:DataType xmi.id=""X.12"" name=""void"" visibility=""public"" isSpecification=""false"" isRoot=""false"" isLeaf=""false"" isAbstract=""false""/>" +
			@"	<UML:DataType xmi.id=""X.13"" name=""bool"" visibility=""public"" isSpecification=""false"" isRoot=""false"" isLeaf=""false"" isAbstract=""false""/>" +
			@"</XMI.content>";


		[Test]
		public void TestLoadOperation()
		{
			Model model = LoadModel(xmiOperations);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(2, cls.Operations.Count);
		}

		[Test]
		public void TestOperationCheckNameAndID()
		{
			Model model = LoadModel(xmiOperations);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(2, cls.Operations.Count);
			Operation op1 = cls.Operations[0] as Operation;
			Operation op2 = cls.Operations[1] as Operation;
			Assert.AreEqual("MethodA", op1.Name);
			Assert.AreEqual("MethodB", op2.Name);
			Assert.AreEqual("UMLOperation.4", op1.Id);
			Assert.AreEqual("UMLOperation.7", op2.Id);
		}

		[Test]
		public void TestOperationParameter()
		{
			Model model = LoadModel(xmiOperations);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(2, cls.Operations.Count);
			Operation op1 = cls.Operations[0] as Operation;
			Operation op2 = cls.Operations[1] as Operation;
			Assert.AreEqual(1, op1.Parameters.Count);
			Assert.AreEqual(1, op2.Parameters.Count);
		}


		[Test]
		public void TestOperationParameterName()
		{
			Model model = LoadModel(xmiOperations);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(2, cls.Operations.Count);
			Operation op1 = cls.Operations[0] as Operation;
			Operation op2 = cls.Operations[1] as Operation;
			Parameter param1 = op1.Parameters[0] as Parameter;
			Assert.AreEqual("paramA", param1.Name);
		}


		[Test]
		public void TestOperationParameterType()
		{
			Model model = LoadModel(xmiOperations);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(2, cls.Operations.Count);
			Operation op1 = cls.Operations[0] as Operation;
			Operation op2 = cls.Operations[1] as Operation;
			Parameter param1 = op1.Parameters[0] as Parameter;
			Assert.AreEqual("string", param1.Type.Name);
		}

		[Test]
		public void TestOperationParameterReturnType()
		{
			Model model = LoadModel(xmiOperations);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(2, cls.Operations.Count);
			Operation op1 = cls.Operations[0] as Operation;
			Operation op2 = cls.Operations[1] as Operation;
			Assert.AreEqual("int", op1.ReturnType.Name);
		}




		string xmiOperationStereotype =
			@"<XMI.content xmlns:UML=""href://org.omg/UML/1.3"">" +
			@"<UML:Class xmi.id=""UMLClass.3"" name=""TestClass"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" isActive=""false"">" +
			@"  <UML:Classifier.feature>" +
			@"    <UML:Operation xmi.id=""UMLOperation.4"" name=""MethodWithStereotype"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" isQuery=""false"" concurrency=""sequential"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" specification="""" owner=""UMLClass.3"">" +
			@"      <UML:BehavioralFeature.parameter>" +
			@"        <UML:Parameter xmi.id=""UMLParameter.5"" name="""" visibility=""public"" isSpecification=""false"" kind=""return"" behavioralFeature=""UMLOperation.4"" type=""X.7""/>" +
			@"      </UML:BehavioralFeature.parameter>" +
			@"    </UML:Operation>" +
			@"  </UML:Classifier.feature>" +
			@"</UML:Class>" +
			@"<UML:Stereotype xmi.id=""X.6"" name=""Finder"" extendedElement=""UMLOperation.4""/>"+
			@"</XMI.content>";


		[Test]
		public void TestOperationStereotype()
		{
			Model model = LoadModel(xmiOperationStereotype);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(1, cls.Operations.Count);
			Operation op1 = cls.Operations[0] as Operation;
			Assert.AreEqual(Stereotype.Finder, op1.Stereotype);
		}

		string xmiTaggedValues = 
			@"<XMI.content xmlns:UML=""href://org.omg/UML/1.3"">"+
			@"	<UML:Class xmi.id=""UMLClass.3"" name=""TestClass"" visibility=""public"" isSpecification=""false"" namespace=""UMLPackage.2"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" isActive=""false"">"+
			@"		<UML:Classifier.feature>"+
			@"			<UML:Attribute xmi.id=""UMLAttribute.4"" name=""MyValue"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" changeability=""changeable"" targetScope=""instance"" type=""X.11"" owner=""UMLClass.3""/>"+
			@"			<UML:Operation xmi.id=""UMLOperation.5"" name=""MyOperation"" visibility=""public"" isSpecification=""false"" ownerScope=""instance"" isQuery=""false"" concurrency=""sequential"" isRoot=""false"" isLeaf=""false"" isAbstract=""false"" specification="""" owner=""UMLClass.3"">"+
			@"				<UML:BehavioralFeature.parameter>"+
			@"					<UML:Parameter xmi.id=""UMLParameter.6"" name="""" visibility=""public"" isSpecification=""false"" kind=""return"" behavioralFeature=""UMLOperation.5"" type=""X.8""/>"+
			@"				</UML:BehavioralFeature.parameter>"+
			@"			</UML:Operation>"+
			@"		</UML:Classifier.feature>"+
			@"	</UML:Class>"+
			@"	<UML:DataType xmi.id=""X.8"" name=""void"" visibility=""public"" isSpecification=""false"" isRoot=""false"" isLeaf=""false"" isAbstract=""false""/>"+
			@"	<UML:DataType xmi.id=""X.11"" name=""int"" visibility=""public"" isSpecification=""false"" isRoot=""false"" isLeaf=""false"" isAbstract=""false""/>"+
			@"	<UML:TaggedValue xmi.id=""X.7"" tag=""sql"" value=""SomeSql"" modelElement=""UMLOperation.5""/>"+
			@"	<UML:TaggedValue xmi.id=""X.9"" tag=""column"" value=""MY_VALUE"" modelElement=""UMLAttribute.4""/>"+
			@"	<UML:TaggedValue xmi.id=""X.10"" tag=""ordering"" value=""unordered"" modelElement=""UMLAttribute.4""/>"+
			@"</XMI.content>";


		[Test]
		public void TestOperationTaggedValue()
		{
			Model model = LoadModel(xmiTaggedValues);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(1, cls.Operations.Count);
			Operation op1 = cls.Operations[0] as Operation;
			Assert.AreEqual(1, op1.TaggedValues.Count);
			TaggedValue tv = op1.TaggedValues[0] as TaggedValue;
			Assert.AreEqual("sql", tv.Key);
			Assert.AreEqual("SomeSql", tv.Value);
		}

		[Test]
		public void TestAttributeTaggedValue()
		{
			Model model = LoadModel(xmiTaggedValues);
			Class cls = model.Classes[0] as Class;
			Assert.AreEqual(1, cls.Attributes.Count);			
			Attribute attr1 = cls.Attributes[0];
			TaggedValue tv = attr1.TaggedValues[0] as TaggedValue;
			Assert.AreEqual("column", tv.Key);
			Assert.AreEqual("MY_VALUE", tv.Value);
		}
	}
}
